package com.jinmdz.fmis.api.api.service;

import com.jinmdz.fmis.api.api.model.common.IdVersionData;
import com.jinmdz.fmis.api.api.model.facelift.FaceLiftData;
import com.jinmdz.fmis.api.api.model.funeral.negotiation.NegotiationFaceLiftItem;
import com.jinmdz.fmis.api.base.BaseService;
import com.jinmdz.fmis.api.model.config.dictionary.BusinessLogCode;
import com.jinmdz.fmis.api.model.config.dictionary.OperationLogCode;
import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.api.wrapper.ChargeWrapper;
import com.jinmdz.fmis.api.wrapper.OperationWrapper;
import com.jinmdz.fmis.common.ext.StringBuilderExt;
import com.jinmdz.fmis.common.util.BeanUtil;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.constant.EBusinessType;
import com.jinmdz.fmis.core.exception.ActionException;
import com.jinmdz.fmis.core.util.JacksonUtil;
import com.jinmdz.fmis.dao.dao.ChargeItemDao;
import com.jinmdz.fmis.dao.dao.FaceLiftItemDao;
import com.jinmdz.fmis.dao.dao.FuneralBusinessDao;
import com.jinmdz.fmis.dao.model.charge.ChargeItem;
import com.jinmdz.fmis.dao.model.facelift.FaceLiftChargeItem;
import com.jinmdz.fmis.dao.model.facelift.FaceLiftItem;
import com.jinmdz.fmis.dao.model.funeral.FuneralBusinessViewItem;
import com.jinmdz.fmis.mapper.entity.ChargeItemEntity;
import com.jinmdz.fmis.mapper.entity.FaceLiftItemEntity;
import com.jinmdz.fmis.mapper.entity.FuneralBusinessLogEntity;
import com.jinmdz.fmis.mapper.mapper.ChargeItemMapper;
import com.jinmdz.fmis.mapper.mapper.FaceLiftItemMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;

import static com.jinmdz.fmis.api.constant.MessageConst.NO_FUNERAL_CODE;

/**
 * 整容FaceLiftService类
 *
 * @author GuanKui
 * @date 2020-01-20 11:30
 */
@Service("faceLiftService")
public class FaceLiftService extends BaseService {

    @Resource
    private FuneralBusinessDao funeralBusinessDao;

    @Resource
    private ChargeItemDao chargeItemDao;

    @Resource
    private ChargeWrapper chargeWrapper;

    @Resource
    private FaceLiftItemDao faceLiftItemDao;

    @Resource
    private FaceLiftItemMapper faceLiftItemMapper;

    @Resource
    private ChargeItemMapper chargeItemMapper;

    @Resource
    private OperationWrapper operationWrapper;

    @Resource
    private OperationLogCode operationLogCode;

    @Resource
    private BusinessLogCode businessLogCode;


    /**
     * 添加整容信息
     *
     * @param userItem 当前帐号
     * @param data     请求数据
     * @return
     * @author GuanKui
     * @date 2020/2/17 12:33
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<ArrayList<NegotiationFaceLiftItem>> saveFaceLift(UserItem userItem, FaceLiftData data) throws ActionException {

        String businessCode = data.getBusinessCode();
        // 通过业务编码获取殡葬信息
        FuneralBusinessViewItem funeralItem = funeralBusinessDao.getFuneralBusinessViewByBusinessCode(businessCode);
        if (DataUtil.isNull(funeralItem) || DataUtil.isNull(funeralItem.getId(), funeralItem.getVersion())) {
            throw exception(NO_FUNERAL_CODE);
        }

        //随机码
        String randomCode = EBusinessType.TYPE_OF_FACE_LIFT.getType();

        // 插入整容费用
        ArrayList<ChargeItemEntity> chargeEntities = chargeWrapper.insertGoodsServices(userItem, businessCode, randomCode, EBusinessType.TYPE_OF_FACE_LIFT.getType(), data.getGoodsServices());

        // 插入整容信息
        chargeEntities.forEach(chargeEntity -> {
            // 创建实体
            FaceLiftItemEntity entity = getEntity(userItem, FaceLiftItemEntity.class);
            entity.setBusinessCode(businessCode)
                    .setRandomCode(randomCode)
                    .setServiceItemId(chargeEntity.getServiceItemId())
                    .setChargeId(chargeEntity.getId())
                    .setFinishUserId(0)
                    .setProcessStateCode(0);
            // 插入整容信息
            faceLiftItemMapper.insertFaceLiftItem(entity);

            // 判断业务费用结果
            if (DataUtil.invalid(entity.getId())) {
                throw exception("保存整容信息失败");
            }
        });

        // 添加业务及操作日志
        Integer logTypeCode = operationLogCode.getFaceLiftInsert();
        Integer chargeLogTypeCode = operationLogCode.getChargeInsert();
        saveFaceLiftLog(userItem, funeralItem, data, logTypeCode, chargeLogTypeCode, chargeEntities);

        // 查询所有整容费用
        ArrayList<FaceLiftChargeItem> faceLiftChargeItems = faceLiftItemDao.listFaceLiftChargeByBusinessCode(businessCode);
        // 返回整容及费用信息，直接替换服务洽谈界面的整容及费用信息
        ArrayList<NegotiationFaceLiftItem> loadItems = new ArrayList<>();
        if (faceLiftChargeItems != null && faceLiftChargeItems.size() > 0) {
            for (FaceLiftChargeItem faceLiftChargeItem : faceLiftChargeItems) {
                NegotiationFaceLiftItem negotiationItem = BeanUtil.copy2Bean(faceLiftChargeItem, new NegotiationFaceLiftItem());
                loadItems.add(negotiationItem);
            }
        }

        // 返回响应结果
        return successList(loadItems);
    }

    /**
     * 添加整容日志记录
     *
     * @param userItem          当前帐号
     * @param funeralItem       当前业务
     * @param data              请求数据
     * @param logTypeCode       日志记录类型
     * @param chargeLogTypeCode 费用日志类型
     * @param chargeEntities    费用记录
     * @return
     * @author LiCongLu
     * @date 2020-02-25 16:15
     */
    private void saveFaceLiftLog(UserItem userItem, FuneralBusinessViewItem funeralItem
            , FaceLiftData data, Integer logTypeCode, Integer chargeLogTypeCode
            , ArrayList<ChargeItemEntity> chargeEntities) throws ActionException {

        // 添加业务日志及操作日志
        String businessCode = funeralItem.getBusinessCode();
        Integer typeCode = businessLogCode.getFaceLiftInsert();
        FuneralBusinessLogEntity businessLogEntity = operationWrapper.businessLog(userItem, businessCode, typeCode);

        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("添加整容信息，业务编码[{0}]，逝者姓名[{1}]，操作人员[{2}]"
                , businessCode, funeralItem.getDeadName()
                , userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, businessLogEntity, logTypeCode, builder);

        // 累计费用总金额
        if (DataUtil.valid(chargeEntities)) {
            BigDecimal sumCharge = new BigDecimal(0);
            for (ChargeItemEntity chargeEntity : chargeEntities) {
                sumCharge = sumCharge.add(chargeEntity.getItemCharge());
            }

            // 添加物品服务费用日志
            builder.clear();
            builder.format("添加整容信息物品服务，业务编码[{0}]，逝者姓名[{1}]，物品服务总金额[{2}]"
                    , businessCode, funeralItem.getDeadName(), DataUtil.getPlainString(sumCharge));
            operationWrapper.operationLog(userItem, businessLogEntity, chargeLogTypeCode
                    , builder.toString(), JacksonUtil.obj2Json(data.getGoodsServices()), null, JacksonUtil.obj2Json(chargeEntities));
        }
    }

    /**
     * 根据face_lift_item.ID删除整容信息
     *
     * @param userItem 当前帐号
     * @param data     主键和本版号
     * @return
     * @author GuanKui
     * @date 2020/2/17 12:49
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteFaceLiftWithId(UserItem userItem, IdVersionData data) throws ActionException {

        FaceLiftItem loadItem = faceLiftItemDao.getFaceLiftItemById(data.getId());

        if (DataUtil.isNull(loadItem) || DataUtil.isNull(loadItem.getId(), loadItem.getVersion())) {
            return failure("主键错误，不存在此整容业务");
        }

        // 验证信息版本
        if (!DataUtil.equals(loadItem.getVersion(), data.getVersion())) {
            return failure(versionError("整容信息"));
        }

        // 判断整容费用是否存在
        ChargeItem chargeItem = chargeItemDao.getChargeItemById(loadItem.getChargeId());
        // 判断是否结算
        if (DataUtil.valid(chargeItem.getAsSettled())) {
            return failure("整容业务费用已经结算，无法进行删除");
        }

        // 判断是否结算
        if (DataUtil.valid(chargeItem.getAsSettled())) {
            return failure("费用已经结算，无法进行删除");
        }

        // 判断是否退费
        if (DataUtil.valid(chargeItem.getAsRefund())
                || DataUtil.valid(chargeItem.getRefundId())) {
            return failure("费用为退费关联费用，无法进行删除");
        }

        // 验证是否业务费用
        if (DataUtil.valid(chargeItem.getAsBusiness())) {
            return failure("此费用为业务费用，无法进行修改");
        }

        // 删除费用
        chargeItemMapper.deletedForChargeItem(chargeItem.getId(), userItem.getId(), chargeItem.getVersion());

        // 删除整容
        faceLiftItemMapper.deletedForFaceLiftItem(data.getId(), userItem.getId(), data.getVersion());

        // 删除日志信息
        deleteFaceLiftLog(userItem, loadItem, chargeItem);

        return success("删除完成");
    }

    /**
     * 删除整容日志
     *
     * @param userItem   当前账号
     * @param loadItem   接运任务
     * @param chargeItem 业务费用
     * @return
     * @author LiCongLu
     * @date 2020-02-25 16:25
     */
    private void deleteFaceLiftLog(UserItem userItem, FaceLiftItem loadItem, ChargeItem chargeItem) throws ActionException {
        // 添加业务日志及操作日志
        String businessCode = loadItem.getBusinessCode();
        Integer typeCode = businessLogCode.getFaceLiftDelete();
        FuneralBusinessLogEntity businessLogEntity = operationWrapper.businessLog(userItem, businessCode, typeCode);
        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("删除整容信息，业务编码[{0}]，操作人员[{1}]", businessCode, userItem.getFullName());
        // 添加日志
        Integer logTypeCode = operationLogCode.getFaceLiftUpdate();
        operationWrapper.operationLog(userItem, businessLogEntity, logTypeCode, builder.toString(), null, JacksonUtil.obj2Json(loadItem), null);

        // 累计费用总金额
        Integer chargeLogTypeCode = operationLogCode.getChargeDelete();
        // 添加整容费用日志
        builder.clear();
        builder.format("删除整容信息物品服务，业务编码[{0}]，整容费用[{1}]", businessCode
                , DataUtil.getPlainString(chargeItem.getItemCharge()));
        operationWrapper.operationLog(userItem, businessLogEntity, chargeLogTypeCode
                , builder.toString(), null, JacksonUtil.obj2Json(chargeItem), null);
    }

}
